package com.leon.datalink.core.persistence.state;

import com.leon.datalink.core.serializer.ProtostuffSerializable;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 节点状态类
 * 保存节点的运行时状态信息
 * 
 * @author leon
 */
public class NodeState implements ProtostuffSerializable {
    
    private String nodeId;
    private Map<String, Object> properties;
    private NodeStatus status;
    private AtomicLong processedCount;
    private AtomicLong errorCount;
    private long lastProcessTime;
    private long createdTime;
    private long lastConfigTime;
    private long lastProcessedTime;
    private long lastEventTime;
    private String lastMessageType;
    
    // 统计信息
    private long totalProcessingTime;
    private Map<Integer, Long> portOutputCounts;
    
    public NodeState() {
        // 默认构造函数，用于序列化
        this.properties = new ConcurrentHashMap<>();
        this.processedCount = new AtomicLong(0);
        this.errorCount = new AtomicLong(0);
        this.portOutputCounts = new ConcurrentHashMap<>();
        this.status = NodeStatus.CREATED;
        this.createdTime = System.currentTimeMillis();
    }
    
    public NodeState(String nodeId) {
        this();
        this.nodeId = nodeId;
    }
    
    public String getNodeId() {
        return nodeId;
    }
    
    public void setNodeId(String nodeId) {
        this.nodeId = nodeId;
    }
    
    public Map<String, Object> getProperties() {
        return properties;
    }
    
    public void setProperties(Map<String, Object> properties) {
        this.properties = properties;
        this.lastConfigTime = System.currentTimeMillis();
    }
    
    public NodeStatus getStatus() {
        return status;
    }
    
    public void setStatus(NodeStatus status) {
        this.status = status;
    }
    
    public long getProcessedCount() {
        return processedCount.get();
    }
    
    public void incrementProcessedCount() {
        this.processedCount.incrementAndGet();
    }
    
    public long getErrorCount() {
        return errorCount.get();
    }
    
    public void incrementErrorCount() {
        this.errorCount.incrementAndGet();
    }
    
    public long getLastProcessTime() {
        return lastProcessTime;
    }
    
    public void setLastProcessTime(long lastProcessTime) {
        this.lastProcessTime = lastProcessTime;
    }
    
    public long getCreatedTime() {
        return createdTime;
    }
    
    public void setCreatedTime(long createdTime) {
        this.createdTime = createdTime;
    }
    
    public long getLastConfigTime() {
        return lastConfigTime;
    }
    
    public void setLastConfigTime(long lastConfigTime) {
        this.lastConfigTime = lastConfigTime;
    }
    
    public long getTotalProcessingTime() {
        return totalProcessingTime;
    }
    
    public void addProcessingTime(long processingTime) {
        this.totalProcessingTime += processingTime;
    }
    
    public double getAverageProcessingTime() {
        long count = getProcessedCount();
        return count > 0 ? (double) totalProcessingTime / count : 0.0;
    }
    
    public Map<Integer, Long> getPortOutputCounts() {
        return portOutputCounts;
    }
    
    public void incrementPortOutputCount(int portIndex) {
        portOutputCounts.merge(portIndex, 1L, Long::sum);
    }
    
    public void setProcessedCount(long processedCount) {
        this.processedCount.set(processedCount);
    }
    
    public void setErrorCount(long errorCount) {
        this.errorCount.set(errorCount);
    }
    
    public void setTotalProcessingTime(long totalProcessingTime) {
        this.totalProcessingTime = totalProcessingTime;
    }
    
    public void setPortOutputCounts(Map<Integer, Long> portOutputCounts) {
        this.portOutputCounts = portOutputCounts;
    }

    public long getLastProcessedTime() {
        return lastProcessedTime;
    }

    public void setLastProcessedTime(long lastProcessedTime) {
        this.lastProcessedTime = lastProcessedTime;
    }

    public long getLastEventTime() {
        return lastEventTime;
    }

    public void setLastEventTime(long lastEventTime) {
        this.lastEventTime = lastEventTime;
    }

    public String getLastMessageType() {
        return lastMessageType;
    }

    public void setLastMessageType(String lastMessageType) {
        this.lastMessageType = lastMessageType;
    }
    
    @Override
    public String toString() {
        return "NodeState{" +
                "nodeId='" + nodeId + '\'' +
                ", status=" + status +
                ", processedCount=" + processedCount.get() +
                ", errorCount=" + errorCount.get() +
                ", lastProcessTime=" + lastProcessTime +
                ", createdTime=" + createdTime +
                '}';
    }
}
